//
// Created by tcj on 2022/2/21.
//

#include "thread.h"
#include "log.h"
#include "util.h"

namespace sylar{

//    thread_local相当于通过将可变变量让每一个线程都拥有独立的副本，
//    从而实现线程封装的机制
//    指向当前线程
    static thread_local Thread* t_thread = nullptr;
    static thread_local std::string t_thread_name = "UNKNOW";

    static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");

    sylar::Semphore::Semphore(uint32_t count) {
        if(sem_init(&m_semaphore,0,count)){
            throw std::logic_error("sem_init error");
        }
    }

    sylar::Semphore::~Semphore() {
        sem_destroy(&m_semaphore);
    }

//    P操作(减1)---sem_wait
    void sylar::Semphore::wait() {
        while(true){
            if(!sem_wait(&m_semaphore)){
                return;
            }
        }
    }

    // V操作(加1)--- sem_post
    void sylar::Semphore::notify() {
        if(sem_post(&m_semaphore)){
            throw std::logic_error("sem_post error");
        }
    }




    Thread* sylar::Thread::GetThis() {
        return t_thread;
    }

    const std::string &sylar::Thread::GetName() {
        return t_thread_name;
    }

    void sylar::Thread::SetName(const std::string &name) {
        if(name.empty()){
            return;
        }
        if(t_thread){
            t_thread->m_name = name;
        }
        t_thread_name = name;
    }

    sylar::Thread::Thread(std::function<void()> cb, const std::string &name)
        :m_cb(cb),m_name(name){
        if(name.empty()){
            m_name = "UNKNOW";
        }
        int rt = pthread_create(&m_thread, nullptr,&Thread::run,this);
        if(rt){
            SYLAR_LOG_ERROR(g_logger) << "pthread_create thread fail,rt="
                <<rt<<" name="<<name;
            throw std::logic_error("pthread_create error");
        }
        m_semphore.wait();
    }

    sylar::Thread::~Thread() {
        if(m_thread){
            pthread_detach(m_thread);
        }
    }
    void sylar::Thread::join() {
        if(m_thread){
            int rt = pthread_join(m_thread,nullptr);
            if(rt){
                SYLAR_LOG_ERROR(g_logger) << "pthread_join thread fail,rt="
                                          <<rt<<" name="<<m_name;
                throw std::logic_error("pthread_join error");
            }
            m_thread =0;
        }
    }

    void* sylar::Thread::run(void *arg) {
//        就是上文说的thread_create()函数中的this
        Thread* thread = (Thread*)arg;
        t_thread = thread;
        t_thread_name = thread->m_name;
        thread->m_id = sylar::GetThreadId();
//        给线程命名
        pthread_setname_np(pthread_self(),thread->m_name.substr(0,15).c_str());

        std::function<void()> cb;
        cb.swap(thread->m_cb);
        thread->m_semphore.notify();
        cb();
        return 0;
    }


}
